-- =====================================================
-- 技术文档管理 - 完整数据库初始化脚本
-- =====================================================
-- 数据库：PostgreSQL 14+
-- 用途：创建所有表结构（文档管理 + 用户认证）
-- 版本：v2.0 (Phase 2 完整版)
-- 日期：2025-10-26
-- =====================================================

-- =====================================================
-- 1. 创建扩展
-- =====================================================

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
CREATE EXTENSION IF NOT EXISTS pg_trgm;

-- =====================================================
-- 2. 删除已存在的表（开发环境，谨慎使用！）
-- =====================================================

DROP TABLE IF EXISTS audit_logs CASCADE;
DROP TABLE IF EXISTS sessions CASCADE;
DROP TABLE IF EXISTS user_permissions CASCADE;
DROP TABLE IF EXISTS role_permissions CASCADE;
DROP TABLE IF EXISTS permissions CASCADE;
DROP TABLE IF EXISTS users CASCADE;
DROP TABLE IF EXISTS roles CASCADE;
DROP TABLE IF EXISTS documents CASCADE;
DROP TABLE IF EXISTS doc_categories CASCADE;

-- =====================================================
-- 3. 创建角色表 (roles)
-- =====================================================

CREATE TABLE roles (
    -- 主键
    id SERIAL PRIMARY KEY,
    
    -- 基本信息
    name VARCHAR(50) UNIQUE NOT NULL,
    display_name VARCHAR(100) NOT NULL,
    description TEXT,
    
    -- 系统角色标识（不可删除）
    is_system BOOLEAN DEFAULT FALSE,
    
    -- 排序
    sort_order INTEGER DEFAULT 0,
    
    -- 时间戳
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE roles IS '角色表 - RBAC 权限模型';
COMMENT ON COLUMN roles.name IS '角色唯一标识，如：admin, editor, viewer';
COMMENT ON COLUMN roles.display_name IS '角色显示名称';
COMMENT ON COLUMN roles.is_system IS '是否为系统角色（不可删除）';

-- =====================================================
-- 4. 创建用户表 (users)
-- =====================================================

CREATE TABLE users (
    -- 主键（UUID，兼容 Supabase）
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    
    -- 认证信息
    email VARCHAR(255) UNIQUE NOT NULL,
    username VARCHAR(100) UNIQUE NOT NULL,
    encrypted_password VARCHAR(255) NOT NULL,
    
    -- 个人信息
    full_name VARCHAR(255),
    avatar_url TEXT,
    bio TEXT,
    phone VARCHAR(20),
    
    -- 角色关联
    role_id INTEGER REFERENCES roles(id) ON DELETE SET NULL,
    
    -- 状态管理
    status VARCHAR(20) DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'banned')),
    email_verified BOOLEAN DEFAULT FALSE,
    email_confirmed_at TIMESTAMP WITH TIME ZONE,
    
    -- Supabase 兼容字段
    raw_app_meta_data JSONB DEFAULT '{}'::jsonb,
    raw_user_meta_data JSONB DEFAULT '{}'::jsonb,
    
    -- 登录信息
    last_sign_in_at TIMESTAMP WITH TIME ZONE,
    last_sign_in_ip INET,
    sign_in_count INTEGER DEFAULT 0,
    
    -- 密码重置
    reset_token VARCHAR(255),
    reset_token_expires_at TIMESTAMP WITH TIME ZONE,
    
    -- 软删除
    deleted_at TIMESTAMP WITH TIME ZONE,
    
    -- 时间戳
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE users IS '用户表 - 兼容 Supabase Auth';
COMMENT ON COLUMN users.id IS 'UUID 主键，兼容 Supabase';
COMMENT ON COLUMN users.email IS '用户邮箱，用于登录';
COMMENT ON COLUMN users.username IS '用户名';
COMMENT ON COLUMN users.encrypted_password IS 'bcrypt 加密的密码';
COMMENT ON COLUMN users.role_id IS '关联角色 ID';
COMMENT ON COLUMN users.status IS '用户状态：active, inactive, banned';
COMMENT ON COLUMN users.raw_app_meta_data IS 'Supabase 兼容 - 应用元数据';
COMMENT ON COLUMN users.raw_user_meta_data IS 'Supabase 兼容 - 用户元数据';

-- =====================================================
-- 5. 创建文档分类表 (doc_categories)
-- =====================================================

CREATE TABLE doc_categories (
    -- 主键
    id SERIAL PRIMARY KEY,
    
    -- 基本信息
    name VARCHAR(100) NOT NULL,
    slug VARCHAR(100) UNIQUE NOT NULL,
    description TEXT,
    icon VARCHAR(50),
    
    -- 树形结构
    parent_id INTEGER REFERENCES doc_categories(id) ON DELETE CASCADE,
    sort_order INTEGER DEFAULT 0,
    
    -- 统计信息
    doc_count INTEGER DEFAULT 0,
    
    -- 状态
    is_active BOOLEAN DEFAULT TRUE,
    
    -- 时间戳
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE doc_categories IS '文档分类表 - 支持多级树形结构';

-- =====================================================
-- 6. 创建文档表 (documents)
-- =====================================================

CREATE TABLE documents (
    -- 主键
    id SERIAL PRIMARY KEY,
    
    -- 基本信息
    title VARCHAR(255) NOT NULL,
    slug VARCHAR(255) UNIQUE NOT NULL,
    summary TEXT,
    
    -- 内容（支持多种来源）
    content TEXT,  -- Markdown 内容（直接存储）
    content_html TEXT,  -- 渲染后的 HTML（可选，用于搜索）
    content_path VARCHAR(500),  -- 文件路径（如：/docs/guide.md）
    content_url TEXT,  -- 外部 URL（如：MinIO 对象存储地址）
    content_base64 TEXT,  -- Base64 编码内容
    content_type VARCHAR(20) DEFAULT 'direct' CHECK (content_type IN ('direct', 'path', 'url', 'base64')),  -- 内容来源类型
    
    -- 关联
    category_id INTEGER REFERENCES doc_categories(id) ON DELETE SET NULL,
    author_id UUID REFERENCES users(id) ON DELETE SET NULL,  -- 关联用户表
    
    -- 标签
    tags TEXT[] DEFAULT '{}',
    
    -- 状态管理
    status VARCHAR(20) DEFAULT 'draft' CHECK (status IN ('draft', 'published', 'archived')),
    is_public BOOLEAN DEFAULT TRUE,
    
    -- 版本
    version INTEGER DEFAULT 1,
    
    -- 作者信息（冗余，提高查询性能）
    author_name VARCHAR(100) DEFAULT 'Admin',
    
    -- 语言
    language VARCHAR(10) DEFAULT 'zh-CN',
    
    -- 统计
    view_count INTEGER DEFAULT 0,
    like_count INTEGER DEFAULT 0,
    
    -- 发布时间
    published_at TIMESTAMP WITH TIME ZONE,
    
    -- 时间戳
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    
    -- 约束
    CONSTRAINT check_documents_version CHECK (version > 0),
    CONSTRAINT check_documents_view_count CHECK (view_count >= 0),
    CONSTRAINT check_documents_like_count CHECK (like_count >= 0)
);

COMMENT ON TABLE documents IS '文档主表';

-- =====================================================
-- 7. 创建权限表 (permissions)
-- =====================================================

CREATE TABLE permissions (
    -- 主键
    id SERIAL PRIMARY KEY,
    
    -- 权限标识
    name VARCHAR(100) UNIQUE NOT NULL,
    display_name VARCHAR(100) NOT NULL,
    description TEXT,
    
    -- 权限分类
    resource VARCHAR(50) NOT NULL,
    action VARCHAR(50) NOT NULL,
    category VARCHAR(50),
    
    -- 排序
    sort_order INTEGER DEFAULT 0,
    
    -- 时间戳
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE permissions IS '权限表 - 细粒度权限定义';
COMMENT ON COLUMN permissions.name IS '权限标识，如：doc:read, doc:write';
COMMENT ON COLUMN permissions.resource IS '资源类型，如：document, user';
COMMENT ON COLUMN permissions.action IS '动作类型，如：read, write, delete';

-- =====================================================
-- 8. 创建角色权限关联表 (role_permissions)
-- =====================================================

CREATE TABLE role_permissions (
    role_id INTEGER NOT NULL REFERENCES roles(id) ON DELETE CASCADE,
    permission_id INTEGER NOT NULL REFERENCES permissions(id) ON DELETE CASCADE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (role_id, permission_id)
);

COMMENT ON TABLE role_permissions IS '角色权限关联表';

-- =====================================================
-- 9. 创建用户权限关联表 (user_permissions)
-- =====================================================

CREATE TABLE user_permissions (
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    permission_id INTEGER NOT NULL REFERENCES permissions(id) ON DELETE CASCADE,
    granted_by UUID REFERENCES users(id) ON DELETE SET NULL,
    grant_reason TEXT,
    expires_at TIMESTAMP WITH TIME ZONE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (user_id, permission_id)
);

COMMENT ON TABLE user_permissions IS '用户额外权限表';

-- =====================================================
-- 10. 创建会话表 (sessions)
-- =====================================================

CREATE TABLE sessions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    refresh_token VARCHAR(500) UNIQUE NOT NULL,
    user_agent TEXT,
    ip_address INET,
    device_type VARCHAR(50),
    device_name VARCHAR(100),
    expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
    is_revoked BOOLEAN DEFAULT FALSE,
    revoked_at TIMESTAMP WITH TIME ZONE,
    revoked_reason TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE sessions IS '用户会话表 - Refresh Token 管理';

-- =====================================================
-- 11. 创建审计日志表 (audit_logs)
-- =====================================================

CREATE TABLE audit_logs (
    id BIGSERIAL PRIMARY KEY,
    user_id UUID REFERENCES users(id) ON DELETE SET NULL,
    user_email VARCHAR(255),
    user_role VARCHAR(50),
    action VARCHAR(100) NOT NULL,
    resource_type VARCHAR(50) NOT NULL,
    resource_id VARCHAR(255),
    ip_address INET,
    user_agent TEXT,
    request_method VARCHAR(10),
    request_url TEXT,
    old_data JSONB,
    new_data JSONB,
    changes JSONB,
    status VARCHAR(20),
    error_message TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE audit_logs IS '审计日志表 - 记录用户操作';

-- =====================================================
-- 12. 创建所有索引
-- =====================================================

-- 12.1 用户表索引
CREATE UNIQUE INDEX uq_users_email ON users(email) WHERE deleted_at IS NULL;
CREATE UNIQUE INDEX uq_users_username ON users(username) WHERE deleted_at IS NULL;
CREATE INDEX idx_users_role_id ON users(role_id);
CREATE INDEX idx_users_status ON users(status);
CREATE INDEX idx_users_created_at_desc ON users(created_at DESC);
CREATE INDEX idx_users_deleted_at ON users(deleted_at);

-- 12.2 角色表索引
CREATE INDEX idx_roles_is_system ON roles(is_system);
CREATE INDEX idx_roles_sort_order ON roles(sort_order);

-- 12.3 权限表索引
CREATE INDEX idx_permissions_resource ON permissions(resource);
CREATE INDEX idx_permissions_category ON permissions(category);
CREATE INDEX idx_permissions_resource_action ON permissions(resource, action);

-- 12.4 分类表索引
CREATE INDEX idx_doc_categories_parent_id ON doc_categories(parent_id);
CREATE INDEX idx_doc_categories_sort_order ON doc_categories(sort_order);

-- 12.5 文档表索引
CREATE INDEX idx_documents_category_id ON documents(category_id);
CREATE INDEX idx_documents_author_id ON documents(author_id);
CREATE INDEX idx_documents_status ON documents(status);
CREATE INDEX idx_documents_category_status ON documents(category_id, status);
CREATE INDEX idx_documents_created_at_desc ON documents(created_at DESC);
CREATE INDEX idx_documents_updated_at_desc ON documents(updated_at DESC);
CREATE INDEX idx_documents_view_count_desc ON documents(view_count DESC);
CREATE INDEX idx_documents_tags ON documents USING GIN(tags);

-- 12.6 关联表索引
CREATE INDEX idx_role_permissions_role_id ON role_permissions(role_id);
CREATE INDEX idx_role_permissions_permission_id ON role_permissions(permission_id);
CREATE INDEX idx_user_permissions_user_id ON user_permissions(user_id);
CREATE INDEX idx_user_permissions_permission_id ON user_permissions(permission_id);
CREATE INDEX idx_user_permissions_expires_at ON user_permissions(expires_at);

-- 12.7 会话表索引
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
CREATE INDEX idx_sessions_expires_at ON sessions(expires_at);
CREATE INDEX idx_sessions_is_revoked ON sessions(is_revoked);

-- 12.8 审计日志表索引
CREATE INDEX idx_audit_logs_user_id ON audit_logs(user_id);
CREATE INDEX idx_audit_logs_action ON audit_logs(action);
CREATE INDEX idx_audit_logs_resource_type ON audit_logs(resource_type);
CREATE INDEX idx_audit_logs_created_at_desc ON audit_logs(created_at DESC);
CREATE INDEX idx_audit_logs_user_action ON audit_logs(user_id, action);

-- =====================================================
-- 13. 创建触发器函数
-- =====================================================

-- 13.1 自动更新 updated_at
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 应用到相关表
CREATE TRIGGER trigger_users_updated_at BEFORE UPDATE ON users
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER trigger_roles_updated_at BEFORE UPDATE ON roles
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER trigger_documents_updated_at BEFORE UPDATE ON documents
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER trigger_doc_categories_updated_at BEFORE UPDATE ON doc_categories
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER trigger_sessions_updated_at BEFORE UPDATE ON sessions
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- 13.2 自动更新分类文档数量
CREATE OR REPLACE FUNCTION update_category_doc_count()
RETURNS TRIGGER AS $$
BEGIN
    IF (TG_OP = 'INSERT') THEN
        UPDATE doc_categories SET doc_count = doc_count + 1 WHERE id = NEW.category_id;
        RETURN NEW;
    END IF;
    
    IF (TG_OP = 'UPDATE' AND OLD.category_id IS DISTINCT FROM NEW.category_id) THEN
        IF OLD.category_id IS NOT NULL THEN
            UPDATE doc_categories SET doc_count = doc_count - 1 WHERE id = OLD.category_id;
        END IF;
        IF NEW.category_id IS NOT NULL THEN
            UPDATE doc_categories SET doc_count = doc_count + 1 WHERE id = NEW.category_id;
        END IF;
        RETURN NEW;
    END IF;
    
    IF (TG_OP = 'DELETE') THEN
        IF OLD.category_id IS NOT NULL THEN
            UPDATE doc_categories SET doc_count = doc_count - 1 WHERE id = OLD.category_id;
        END IF;
        RETURN OLD;
    END IF;
    
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_update_category_doc_count
    AFTER INSERT OR UPDATE OR DELETE ON documents
    FOR EACH ROW EXECUTE FUNCTION update_category_doc_count();

-- 13.3 自动设置发布时间
CREATE OR REPLACE FUNCTION set_published_at()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.status = 'published' 
       AND (OLD.status IS NULL OR OLD.status != 'published')
       AND NEW.published_at IS NULL THEN
        NEW.published_at = CURRENT_TIMESTAMP;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_set_published_at
    BEFORE INSERT OR UPDATE ON documents
    FOR EACH ROW EXECUTE FUNCTION set_published_at();

-- =====================================================
-- 14. 插入初始角色
-- =====================================================

INSERT INTO roles (id, name, display_name, description, is_system, sort_order) VALUES
(1, 'admin', '管理员', '系统管理员，拥有所有权限', true, 1),
(2, 'editor', '编辑', '可以创建和编辑文档', false, 2),
(3, 'viewer', '访客', '只能查看公开文档', false, 3);

-- =====================================================
-- 15. 插入初始权限
-- =====================================================

INSERT INTO permissions (name, display_name, description, resource, action, category, sort_order) VALUES
-- 文档管理
('doc:read', '查看文档', '可以查看所有已发布的文档', 'document', 'read', '文档管理', 1),
('doc:write', '编辑文档', '可以创建和编辑文档', 'document', 'write', '文档管理', 2),
('doc:delete', '删除文档', '可以删除文档', 'document', 'delete', '文档管理', 3),
('doc:publish', '发布文档', '可以发布和取消发布文档', 'document', 'publish', '文档管理', 4),

-- 分类管理
('category:manage', '管理分类', '可以创建、编辑、删除分类', 'category', 'manage', '分类管理', 5),

-- 用户管理
('user:read', '查看用户', '可以查看用户列表和详情', 'user', 'read', '用户管理', 6),
('user:create', '创建用户', '可以创建新用户', 'user', 'create', '用户管理', 7),
('user:update', '编辑用户', '可以编辑用户信息', 'user', 'update', '用户管理', 8),
('user:delete', '删除用户', '可以删除用户', 'user', 'delete', '用户管理', 9),

-- 角色管理
('role:read', '查看角色', '可以查看角色列表', 'role', 'read', '角色管理', 10),
('role:create', '创建角色', '可以创建新角色', 'role', 'create', '角色管理', 11),
('role:update', '编辑角色', '可以编辑角色信息', 'role', 'update', '角色管理', 12),
('role:delete', '删除角色', '可以删除角色', 'role', 'delete', '角色管理', 13),

-- 权限管理
('permission:read', '查看权限', '可以查看权限列表', 'permission', 'read', '权限管理', 14),
('permission:manage', '管理权限', '可以分配和撤销权限', 'permission', 'manage', '权限管理', 15),

-- 系统管理
('system:config', '系统配置', '可以修改系统配置', 'system', 'config', '系统管理', 16);

-- =====================================================
-- 16. 分配权限给角色
-- =====================================================

-- 管理员 - 所有权限
INSERT INTO role_permissions (role_id, permission_id)
SELECT 1, id FROM permissions;

-- 编辑 - 文档和分类权限
INSERT INTO role_permissions (role_id, permission_id)
SELECT 2, id FROM permissions 
WHERE name IN ('doc:read', 'doc:write', 'doc:publish', 'category:manage');

-- 访客 - 只读权限
INSERT INTO role_permissions (role_id, permission_id)
SELECT 3, id FROM permissions 
WHERE name = 'doc:read';

-- =====================================================
-- 17. 创建管理员用户
-- =====================================================

-- 注意：密码 'Admin@123' 的 bcrypt 哈希
-- 实际使用时需要用 bcrypt 生成真实的哈希值
INSERT INTO users (
    email, 
    username, 
    encrypted_password, 
    full_name, 
    role_id, 
    email_verified, 
    status,
    email_confirmed_at
) VALUES (
    'admin@example.com',
    'admin',
    '$2b$10$K7G9cCqYv6VxZqXPZqXPZeE.qF9zKqYv6VxZqXPZqXPZeE.qF9zKq',  -- 请替换为实际的 bcrypt 密码
    '系统管理员',
    1,
    true,
    'active',
    CURRENT_TIMESTAMP
);

-- =====================================================
-- 18. 创建视图
-- =====================================================

-- 已发布文档视图
CREATE OR REPLACE VIEW v_published_documents AS
SELECT 
    d.id,
    d.title,
    d.slug,
    d.summary,
    d.tags,
    d.view_count,
    d.like_count,
    d.published_at,
    d.created_at,
    c.name AS category_name,
    u.username AS author_username,
    u.full_name AS author_full_name
FROM documents d
LEFT JOIN doc_categories c ON d.category_id = c.id
LEFT JOIN users u ON d.author_id = u.id
WHERE d.status = 'published' AND d.is_public = TRUE;

-- 分类树视图
CREATE OR REPLACE VIEW v_category_tree AS
WITH RECURSIVE category_tree AS (
    SELECT 
        id, name, slug, parent_id, sort_order, doc_count,
        0 AS level,
        ARRAY[sort_order, id] AS path
    FROM doc_categories
    WHERE parent_id IS NULL AND is_active = TRUE
    UNION ALL
    SELECT 
        c.id, c.name, c.slug, c.parent_id, c.sort_order, c.doc_count,
        ct.level + 1,
        ct.path || ARRAY[c.sort_order, c.id]
    FROM doc_categories c
    INNER JOIN category_tree ct ON c.parent_id = ct.id
    WHERE c.is_active = TRUE
)
SELECT * FROM category_tree ORDER BY path;

-- =====================================================
-- 19. 完成提示
-- =====================================================

DO $$
BEGIN
    RAISE NOTICE '=================================================';
    RAISE NOTICE '技术文档管理数据库初始化完成！（完整版）';
    RAISE NOTICE '=================================================';
    RAISE NOTICE '创建的表：';
    RAISE NOTICE '  - roles (角色表)';
    RAISE NOTICE '  - users (用户表)';
    RAISE NOTICE '  - doc_categories (分类表)';
    RAISE NOTICE '  - documents (文档表)';
    RAISE NOTICE '  - permissions (权限表)';
    RAISE NOTICE '  - role_permissions (角色权限关联表)';
    RAISE NOTICE '  - user_permissions (用户权限关联表)';
    RAISE NOTICE '  - sessions (会话表)';
    RAISE NOTICE '  - audit_logs (审计日志表)';
    RAISE NOTICE '';
    RAISE NOTICE '初始数据：';
    RAISE NOTICE '  - 3 个角色（admin, editor, viewer）';
    RAISE NOTICE '  - 16 个权限';
    RAISE NOTICE '  - 1 个管理员用户';
    RAISE NOTICE '';
    RAISE NOTICE '下一步：运行测试数据脚本';
    RAISE NOTICE '  psql -U postgres -d doc_management -f 02-database-seed-complete.sql';
    RAISE NOTICE '=================================================';
END $$;

